x86: Various cleanups around CR4 handling, cpu_possible_map, and VMX initialisation.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 12 Jul 2007 10:49:02 +0000 (11:49 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 12 Jul 2007 10:49:02 +0000 (11:49 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
20 files changed:
xen/arch/x86/acpi/power.c
xen/arch/x86/cpu/common.c
xen/arch/x86/crash.c
xen/arch/x86/domain.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/i8259.c
xen/arch/x86/machine_kexec.c
xen/arch/x86/mm.c
xen/arch/x86/shutdown.c
xen/arch/x86/smp.c
xen/arch/x86/smpboot.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/hvm/support.h
xen/include/asm-x86/hvm/vmx/vmcs.h
xen/include/asm-x86/page.h
xen/include/asm-x86/processor.h
xen/include/xen/cpumask.h

index 1bd8e2dfd416e68f17f556bc8bc22ebb16af2810..121327895e49f009ddf7dc5917d1aef652a8f699 100644 (file)
@@ -118,7 +118,7 @@ int enter_state(u32 state)
     
     freeze_domains();
 
-    hvm_suspend_cpu();
+    hvm_cpu_down();
 
     pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n",
         acpi_states[state]);
@@ -152,7 +152,8 @@ int enter_state(u32 state)
  Done:
     local_irq_restore(flags);
 
-    hvm_resume_cpu();
+    if ( !hvm_cpu_up() )
+        BUG();
 
     thaw_domains();
     spin_unlock(&pm_lock);
index 9f018a93c003bf73f71aa90d13f61d0b7b3d3307..433f5a7641580f137a9115f9f5f0a4cf3f487196 100644 (file)
@@ -557,9 +557,6 @@ void __devinit cpu_init(void)
        }
        printk(KERN_INFO "Initializing CPU#%d\n", cpu);
 
-       if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
-               clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
-
        *(unsigned short *)(&gdt_load[0]) = LAST_RESERVED_GDT_BYTE;
        *(unsigned long  *)(&gdt_load[2]) = GDT_VIRT_START(current);
        __asm__ __volatile__ ( "lgdt %0" : "=m" (gdt_load) );
index 57e3af4d719fa7e7c3f5b9a120ffea701f9c8d74..398fd781d2c7d09160bcec573efc8cfb99d34587 100644 (file)
@@ -43,7 +43,7 @@ static int crash_nmi_callback(struct cpu_user_regs *regs, int cpu)
     kexec_crash_save_cpu();
     disable_local_APIC();
     atomic_dec(&waiting_for_crash_ipi);
-    hvm_disable();
+    hvm_cpu_down();
 
     for ( ; ; )
         __asm__ __volatile__ ( "hlt" );
@@ -99,7 +99,7 @@ void machine_crash_shutdown(void)
 
     disable_IO_APIC();
 
-    hvm_disable();
+    hvm_cpu_down();
 
     info = kexec_crash_save_info();
     info->dom0_pfn_to_mfn_frame_list_list =
index f1e4a67c60f2849b256854c1e7a6d8ea3da65ed5..061f0c79764cec25dd471ee62a3875ee19a5e21b 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/msr.h>
+#include <asm/nmi.h>
 #ifdef CONFIG_COMPAT
 #include <compat/vcpu.h>
 #endif
@@ -76,10 +77,7 @@ static void default_idle(void)
         local_irq_enable();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-#include <asm/nmi.h>
-/* We don't actually take CPU down, just spin without interrupts. */
-static inline void play_dead(void)
+static void play_dead(void)
 {
     __cpu_disable();
     /* This must be done before dead CPU ack */
@@ -94,12 +92,6 @@ static inline void play_dead(void)
     for ( ; ; )
         halt();
 }
-#else
-static inline void play_dead(void)
-{
-    BUG();
-}
-#endif /* CONFIG_HOTPLUG_CPU */
 
 void idle_loop(void)
 {
index e5c5a79fdd9c6a1b1ae3b067114c5ffdca52f4e2..27b544598d5f0880f90a85b849fada1e115b387d 100644 (file)
@@ -76,11 +76,6 @@ void hvm_enable(struct hvm_function_table *fns)
     hvm_enabled = 1;
 }
 
-void hvm_disable(void)
-{
-    hvm_suspend_cpu();
-}
-
 void hvm_stts(struct vcpu *v)
 {
     /* FPU state already dirty? Then no need to setup_fpu() lazily. */
index 1596a555788ac805f10c17b7e8e0b9cf723ad798..2b75b1fd45470d49240f5408130e40efedb2319f 100644 (file)
@@ -94,7 +94,7 @@ static void svm_inject_exception(struct vcpu *v, int trap,
     vmcb->eventinj = event;
 }
 
-static void svm_suspend_cpu(void)
+static void svm_cpu_down(void)
 {
     write_efer(read_efer() & ~EFER_SVME);
 }
@@ -973,7 +973,7 @@ static int svm_event_injection_faulted(struct vcpu *v)
 
 static struct hvm_function_table svm_function_table = {
     .name                 = "SVM",
-    .suspend_cpu          = svm_suspend_cpu,
+    .cpu_down             = svm_cpu_down,
     .domain_initialise    = svm_domain_initialise,
     .domain_destroy       = svm_domain_destroy,
     .vcpu_initialise      = svm_vcpu_initialise,
index 72d56ccf4a7ad8f583681c24348253dd5b454e31..17d3724bc8b8e5b895b0f56dcb2e8f0a0cfe2ae9 100644 (file)
@@ -66,7 +66,7 @@ static u32 adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, u32 msr)
     return ctl;
 }
 
-void vmx_init_vmcs_config(void)
+static void vmx_init_vmcs_config(void)
 {
     u32 vmx_msr_low, vmx_msr_high, min, opt;
     u32 _vmx_pin_based_exec_control;
@@ -130,8 +130,9 @@ void vmx_init_vmcs_config(void)
 
     rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
 
-    if ( smp_processor_id() == 0 )
+    if ( !vmx_pin_based_exec_control )
     {
+        /* First time through. */
         vmcs_revision_id = vmx_msr_low;
         vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
         vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
@@ -142,6 +143,7 @@ void vmx_init_vmcs_config(void)
     }
     else
     {
+        /* Globals are already initialised: re-check them. */
         BUG_ON(vmcs_revision_id != vmx_msr_low);
         BUG_ON(vmx_pin_based_exec_control != _vmx_pin_based_exec_control);
         BUG_ON(vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control);
@@ -189,7 +191,7 @@ static void __vmx_clear_vmcs(void *info)
     struct vcpu *v = info;
     struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
 
-    /* Otherwise we can nest (vmx_suspend_cpu() vs. vmx_clear_vmcs()). */
+    /* Otherwise we can nest (vmx_cpu_down() vs. vmx_clear_vmcs()). */
     ASSERT(!local_irq_is_enabled());
 
     if ( arch_vmx->active_cpu == smp_processor_id() )
@@ -234,7 +236,54 @@ static void vmx_load_vmcs(struct vcpu *v)
     local_irq_restore(flags);
 }
 
-void vmx_suspend_cpu(void)
+int vmx_cpu_up(void)
+{
+    u32 eax, edx;
+    int cpu = smp_processor_id();
+
+    BUG_ON(!(read_cr4() & X86_CR4_VMXE));
+
+    rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
+
+    if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
+    {
+        if ( !(eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) )
+        {
+            printk("CPU%d: VMX disabled\n", cpu);
+            return 0;
+        }
+    }
+    else
+    {
+        wrmsr(IA32_FEATURE_CONTROL_MSR,
+              IA32_FEATURE_CONTROL_MSR_LOCK |
+              IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0);
+    }
+
+    vmx_init_vmcs_config();
+
+    INIT_LIST_HEAD(&this_cpu(active_vmcs_list));
+
+    if ( this_cpu(host_vmcs) == NULL )
+    {
+        this_cpu(host_vmcs) = vmx_alloc_vmcs();
+        if ( this_cpu(host_vmcs) == NULL )
+        {
+            printk("CPU%d: Could not allocate host VMCS\n", cpu);
+            return 0;
+        }
+    }
+
+    if ( __vmxon(virt_to_maddr(this_cpu(host_vmcs))) )
+    {
+        printk("CPU%d: VMXON failed\n", cpu);
+        return 0;
+    }
+
+    return 1;
+}
+
+void vmx_cpu_down(void)
 {
     struct list_head *active_vmcs_list = &this_cpu(active_vmcs_list);
     unsigned long flags;
@@ -245,25 +294,12 @@ void vmx_suspend_cpu(void)
         __vmx_clear_vmcs(list_entry(active_vmcs_list->next,
                                     struct vcpu, arch.hvm_vmx.active_list));
 
-    if ( read_cr4() & X86_CR4_VMXE )
-    {
-        __vmxoff();
-        clear_in_cr4(X86_CR4_VMXE);
-    }
+    BUG_ON(!(read_cr4() & X86_CR4_VMXE));
+    __vmxoff();
 
     local_irq_restore(flags);
 }
 
-void vmx_resume_cpu(void)
-{
-    if ( !read_cr4() & X86_CR4_VMXE )
-    {
-        set_in_cr4(X86_CR4_VMXE);
-        if ( __vmxon(virt_to_maddr(this_cpu(host_vmcs))) )
-            BUG();
-    }
-}
-
 void vmx_vmcs_enter(struct vcpu *v)
 {
     /*
@@ -294,21 +330,6 @@ void vmx_vmcs_exit(struct vcpu *v)
     vcpu_unpause(v);
 }
 
-struct vmcs_struct *vmx_alloc_host_vmcs(void)
-{
-    ASSERT(this_cpu(host_vmcs) == NULL);
-    this_cpu(host_vmcs) = vmx_alloc_vmcs();
-    INIT_LIST_HEAD(&this_cpu(active_vmcs_list));
-    return this_cpu(host_vmcs);
-}
-
-void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
-{
-    ASSERT(vmcs == this_cpu(host_vmcs));
-    vmx_free_vmcs(vmcs);
-    this_cpu(host_vmcs) = NULL;
-}
-
 struct xgt_desc {
     unsigned short size;
     unsigned long address __attribute__((packed));
index 5cb11863e4a468ddf2fc661117d0909e9f1663db..ccf3a8fad0d92e824be5114b17b0f8bf64fc6839 100644 (file)
@@ -1262,66 +1262,44 @@ static struct hvm_function_table vmx_function_table = {
     .init_ap_context      = vmx_init_ap_context,
     .init_hypercall_page  = vmx_init_hypercall_page,
     .event_injection_faulted = vmx_event_injection_faulted,
-    .suspend_cpu          = vmx_suspend_cpu,
-    .resume_cpu           = vmx_resume_cpu,
+    .cpu_up               = vmx_cpu_up,
+    .cpu_down             = vmx_cpu_down,
 };
 
-int start_vmx(void)
+void start_vmx(void)
 {
-    u32 eax, edx;
-    struct vmcs_struct *vmcs;
+    static int bootstrapped;
 
-    /*
-     * Xen does not fill x86_capability words except 0.
-     */
-    boot_cpu_data.x86_capability[4] = cpuid_ecx(1);
-
-    if ( !test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability) )
-        return 0;
-
-    rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
-
-    if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
+    if ( bootstrapped )
     {
-        if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0 )
+        if ( hvm_enabled && !vmx_cpu_up() )
         {
-            printk("VMX disabled by Feature Control MSR.\n");
-            return 0;
+            printk("VMX: FATAL: failed to initialise CPU%d!\n",
+                   smp_processor_id());
+            BUG();
         }
-    }
-    else
-    {
-        wrmsr(IA32_FEATURE_CONTROL_MSR,
-              IA32_FEATURE_CONTROL_MSR_LOCK |
-              IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0);
+        return;
     }
 
-    set_in_cr4(X86_CR4_VMXE);
+    bootstrapped = 1;
 
-    vmx_init_vmcs_config();
+    /* Xen does not fill x86_capability words except 0. */
+    boot_cpu_data.x86_capability[4] = cpuid_ecx(1);
 
-    if ( smp_processor_id() == 0 )
-        setup_vmcs_dump();
+    if ( !test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability) )
+        return;
 
-    if ( (vmcs = vmx_alloc_host_vmcs()) == NULL )
-    {
-        clear_in_cr4(X86_CR4_VMXE);
-        printk("Failed to allocate host VMCS\n");
-        return 0;
-    }
+    set_in_cr4(X86_CR4_VMXE);
 
-    if ( __vmxon(virt_to_maddr(vmcs)) )
+    if ( !vmx_cpu_up() )
     {
-        clear_in_cr4(X86_CR4_VMXE);
-        printk("VMXON failed\n");
-        vmx_free_host_vmcs(vmcs);
-        return 0;
+        printk("VMX: failed to initialise.\n");
+        return;
     }
 
-    vmx_save_host_msrs();
+    setup_vmcs_dump();
 
-    if ( smp_processor_id() != 0 )
-        return 1;
+    vmx_save_host_msrs();
 
     hvm_enable(&vmx_function_table);
 
@@ -1339,8 +1317,6 @@ int start_vmx(void)
         disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP);
         disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP);
     }
-
-    return 1;
 }
 
 /*
index b02606af39d5b0c5e30ae347c2e7f1d7139d71a3..70eccd773aa3c2444544262d4b653d4cce0918bc 100644 (file)
@@ -397,7 +397,8 @@ void __init init_IRQ(void)
         irq_desc[i].depth   = 1;
         spin_lock_init(&irq_desc[i].lock);
         cpus_setall(irq_desc[i].affinity);
-        set_intr_gate(i, interrupt[i]);
+        if ( i >= 0x20 )
+            set_intr_gate(i, interrupt[i]);
     }
 
     for ( i = 0; i < 16; i++ )
index e5033da55b3d0574a67954024423bb673dd5f1cd..8fbd1ab164092e9c6b1d2e46ae166be310598bd9 100644 (file)
@@ -82,10 +82,8 @@ static void __machine_reboot_kexec(void *data)
 
     smp_send_stop();
 
-#ifdef CONFIG_X86_IO_APIC
     disable_IO_APIC();
-#endif
-    hvm_disable();
+    hvm_cpu_down();
 
     machine_kexec(image);
 }
index c627af93bcc78e46f133c830882196217e81a4c6..cbdfd8875a7218dce420308b8c770609e31197fd 100644 (file)
@@ -3642,8 +3642,6 @@ static void __memguard_change_range(void *p, unsigned long l, int guard)
     unsigned long flags = __PAGE_HYPERVISOR | MAP_SMALL_PAGES;
 
     /* Ensure we are dealing with a page-aligned whole number of pages. */
-    ASSERT((_p&PAGE_MASK) != 0);
-    ASSERT((_l&PAGE_MASK) != 0);
     ASSERT((_p&~PAGE_MASK) == 0);
     ASSERT((_l&~PAGE_MASK) == 0);
 
index 441144b830f77bc0c5b3e846148ca24cc294b2a2..5fbecc088ea92635c2d5bbffc230f2fc97269017 100644 (file)
@@ -222,7 +222,7 @@ void machine_restart(char *cmd)
      */
     smp_send_stop();
     disable_IO_APIC();
-    hvm_disable();
+    hvm_cpu_down();
 
     /* Rebooting needs to touch the page at absolute address 0. */
     *((unsigned short *)__va(0x472)) = reboot_mode;
index 05c3fb4c3cc1944dd2e73fd5cd2cd84234f97643..31fc8adbe6f283ff5419e92241f0be12ac9f92ff 100644 (file)
@@ -310,7 +310,7 @@ static void stop_this_cpu (void *dummy)
 
     local_irq_disable();
     disable_local_APIC();
-    hvm_disable();
+    hvm_cpu_down();
 
     for ( ; ; )
         __asm__ __volatile__ ( "hlt" );
index 8dac0a699db17e9f6f720b99b08ca1a695a5ef32..6c19fb4db05d27070fb3a0e1fbe2926902e6abf0 100644 (file)
@@ -87,11 +87,7 @@ EXPORT_SYMBOL(cpu_online_map);
 cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
 EXPORT_SYMBOL(cpu_callout_map);
-#ifdef CONFIG_HOTPLUG_CPU
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
-#else
 cpumask_t cpu_possible_map;
-#endif
 EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
index 10db897ef3e0961ef343397f4d004b33d523affb..275a5b52c062293c13faf55cb359b6a63e66f45e 100644 (file)
@@ -156,8 +156,8 @@ struct hvm_function_table {
 
     int  (*event_injection_faulted)(struct vcpu *v);
 
-    void (*suspend_cpu)(void);
-    void (*resume_cpu)(void);
+    int  (*cpu_up)(void);
+    void (*cpu_down)(void);
 };
 
 extern struct hvm_function_table hvm_funcs;
@@ -314,16 +314,17 @@ static inline int hvm_event_injection_faulted(struct vcpu *v)
 /* These exceptions must always be intercepted. */
 #define HVM_TRAP_MASK (1U << TRAP_machine_check)
 
-static inline void hvm_suspend_cpu(void)
+static inline int hvm_cpu_up(void)
 {
-    if ( hvm_funcs.suspend_cpu )
-        hvm_funcs.suspend_cpu();
+    if ( hvm_funcs.cpu_up )
+        return hvm_funcs.cpu_up();
+    return 1;
 }
 
-static inline void hvm_resume_cpu(void)
+static inline void hvm_cpu_down(void)
 {
-    if ( hvm_funcs.resume_cpu )
-        hvm_funcs.resume_cpu();
+    if ( hvm_funcs.cpu_down )
+        hvm_funcs.cpu_down();
 }
 
 #endif /* __ASM_X86_HVM_HVM_H__ */
index ac8fb63fda7c676fae85f2e6e751c5b6461254b0..b4d4c17e53f953a1ea407ff50a0a4bd16de5ccd2 100644 (file)
@@ -217,7 +217,6 @@ int hvm_load(struct domain *d, hvm_domain_context_t *h);
 extern char hvm_io_bitmap[];
 
 void hvm_enable(struct hvm_function_table *);
-void hvm_disable(void);
 
 int hvm_copy_to_guest_phys(paddr_t paddr, void *buf, int size);
 int hvm_copy_from_guest_phys(void *buf, paddr_t paddr, int size);
index fbd12a248aaee0b82c2dc1d829ecd0f24c312124..6cf1fadc5071cef696ad0526bbcc011dcd9d4806 100644 (file)
 #include <asm/hvm/vmx/cpu.h>
 #include <public/hvm/vmx_assist.h>
 
-extern int start_vmx(void);
+extern void start_vmx(void);
 extern void vmcs_dump_vcpu(void);
-extern void vmx_init_vmcs_config(void);
 extern void setup_vmcs_dump(void);
-extern void vmx_suspend_cpu(void);
-extern void vmx_resume_cpu(void);
+extern int  vmx_cpu_up(void);
+extern void vmx_cpu_down(void);
 
 struct vmcs_struct {
     u32 vmcs_revision_id;
@@ -89,9 +88,6 @@ struct arch_vmx_struct {
     unsigned char        pm_irqbase[2];
 };
 
-struct vmcs_struct *vmx_alloc_host_vmcs(void);
-void vmx_free_host_vmcs(struct vmcs_struct *vmcs);
-
 int vmx_create_vmcs(struct vcpu *v);
 void vmx_destroy_vmcs(struct vcpu *v);
 void vmx_vmcs_enter(struct vcpu *v);
index 4b4133214b08946011367a2635d4feb5a397155f..1ece136606328e867c08188b3ff2cbdce6a21895 100644 (file)
@@ -294,19 +294,8 @@ void paging_init(void);
 void setup_idle_pagetable(void);
 #endif /* !defined(__ASSEMBLY__) */
 
-#define __pge_off()                                                     \
-    do {                                                                \
-        __asm__ __volatile__(                                           \
-            "mov %0, %%cr4;  # turn off PGE     "                       \
-            : : "r" (mmu_cr4_features & ~X86_CR4_PGE) );                \
-        } while ( 0 )
-
-#define __pge_on()                                                      \
-    do {                                                                \
-        __asm__ __volatile__(                                           \
-            "mov %0, %%cr4;  # turn off PGE     "                       \
-            : : "r" (mmu_cr4_features) );                               \
-    } while ( 0 )
+#define __pge_off() write_cr4(mmu_cr4_features & ~X86_CR4_PGE)
+#define __pge_on()  write_cr4(mmu_cr4_features)
 
 #define _PAGE_PRESENT  0x001U
 #define _PAGE_RW       0x002U
index 9add6de1e924cc7c77df12da892aa3439664d03c..15bac913aee1e819bd8ae6ee94e70de4e34d27ab 100644 (file)
@@ -331,24 +331,8 @@ extern unsigned long mmu_cr4_features;
 
 static always_inline void set_in_cr4 (unsigned long mask)
 {
-    unsigned long dummy;
     mmu_cr4_features |= mask;
-    __asm__ __volatile__ (
-        "mov %%cr4,%0\n\t"
-        "or %1,%0\n\t"
-        "mov %0,%%cr4\n"
-        : "=&r" (dummy) : "irg" (mask) );
-}
-
-static always_inline void clear_in_cr4 (unsigned long mask)
-{
-    unsigned long dummy;
-    mmu_cr4_features &= ~mask;
-    __asm__ __volatile__ (
-        "mov %%cr4,%0\n\t"
-        "and %1,%0\n\t"
-        "mov %0,%%cr4\n"
-        : "=&r" (dummy) : "irg" (~mask) );
+    write_cr4(mmu_cr4_features);
 }
 
 /*
index 7e24f84876f63e7315f4528290db6e799322d19a..a6f8e259422284ef9ea6c6d09bec02a1967cfc95 100644 (file)
@@ -305,7 +305,7 @@ static inline int __cpulist_scnprintf(char *buf, int len,
  * bitmap of size NR_CPUS.
  *
  *  #ifdef CONFIG_HOTPLUG_CPU
- *     cpu_possible_map - all NR_CPUS bits set
+ *     cpu_possible_map - has bit 'cpu' set iff cpu is populatable
  *     cpu_present_map  - has bit 'cpu' set iff cpu is populated
  *     cpu_online_map   - has bit 'cpu' set iff cpu available to scheduler
  *  #else